/**
 * 
 */
package kr.co.insoft.auth.security;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;

import kr.co.insoft.auth.security.codec.AESCodec;
import kr.co.insoft.auth.security.codec.Codec;
import kr.co.insoft.auth.service.codec.WeeklyCodecKeyService;

import org.apache.commons.codec.binary.Base64;
import org.springframework.security.core.Authentication;

/**
 * @author IN-SOFT Inc. GoodwillDD(sylee@in-soft.co.kr)
 * 
 */
public class SecurityCookieService {

	private static final String DEFAULT_COOKIE_PATH = "/";
	private final String cookieName;
	private final String cookiePath;
	private final String cookieDomain;
	private final Codec codec;
	private final int cookieMaxAge;
	private final AuthenticationSerializer serializer;
	final WeeklyCodecKeyService codecKeyService;

	public SecurityCookieService(String cookieName,
			WeeklyCodecKeyService codecKeyService, String cookiePath,
			String cookieDomain) throws Exception {
		this.codecKeyService = codecKeyService;
		this.cookieName = cookieName;
		this.cookiePath = cookiePath;
		this.cookieDomain = cookieDomain;
		this.cookieMaxAge = -1;
		this.codec = new AESCodec(codecKeyService.getSalt());
		this.serializer = new AuthenticationSerializer();
	}

	public SecurityCookieService(String cookieName,
			WeeklyCodecKeyService codecKeyService, String cookieDomain)
			throws Exception {
		this.codecKeyService = codecKeyService;
		this.cookieName = cookieName;
		this.cookiePath = DEFAULT_COOKIE_PATH;
		this.cookieDomain = cookieDomain;
		this.cookieMaxAge = -1;
		this.codec = new AESCodec(codecKeyService.getSalt());
		this.serializer = new AuthenticationSerializer();
	}

	public Authentication getAuthenticationFrom(Cookie cookie) {
		byte[] decodedFromBase64 = Base64.decodeBase64(cookie.getValue());
		byte[] decryptedAuthentication = codec.decrypt(decodedFromBase64);

		return serializer.deserializeFrom(decryptedAuthentication);
	}

	public Cookie createSecurityCookie(Authentication auth) {
		byte[] serializedAuthentication = serializer.serializeToByteArray(auth);
		byte[] encryptedAuthentication = codec
				.encrypt(serializedAuthentication);
		byte[] encodedWithBase64 = Base64
				.encodeBase64URLSafe(encryptedAuthentication);

		String value = new String(encodedWithBase64);
		Cookie c = new Cookie(cookieName, value);
		c.setPath(cookiePath);
		c.setDomain(cookieDomain);
		c.setMaxAge(cookieMaxAge);
		return c;
	}

	public Cookie getSecurityCookieFrom(HttpServletRequest request) {
		Cookie[] cookies = request.getCookies();
		if (cookies != null) {
			for (Cookie cookie : cookies) {
				if (cookie.getName().equals(cookieName)) {
					return cookie;
				}
			}
		}
		return null;
	}

	public Cookie createLogoutCookie() {
		Cookie c = new Cookie(cookieName, "");
		c.setPath(cookiePath);
		c.setDomain(cookieDomain);
		c.setMaxAge(0);
		return c;
	}

	public boolean containsSecurityCookie(HttpServletRequest request) {
		return getSecurityCookieFrom(request) != null;
	}
}
